//
// Created by cube on 2020/10/22.
//

#include <gtest/gtest.h>

#include <iostream>
#include "../Platform/NetBase.h"
#include "../Platform/Multplex.h"

using namespace NetBase;

class My_udp_mul : public Multplex{
public:
    My_udp_mul(const int& count):Multplex(count){
        if(__server.bind(NetAddress(INADDR_ANY,8901))){
            std::cout<<"bind ok"<<std::endl;
            addSocket(__server.getSocket());
        }
    }

    void run_server(){
        while (server() != -1){}
    }

protected:
    bool read(int socket) override {
        NetUdp cli(socket);
        NetAddress addr;
        int8_t buf[1024] = {};
        if(cli.recv(addr,buf,1023) <= 0)return false;
        std::cout<<"read "<<buf<<std::endl;
        int8_t sbuf[] = "my server";
        if(cli.send(addr,sbuf,sizeof(sbuf)) <= 0)return false;
        return true;
    }
    void disConnecct(int socket){
        std::cout<<"socket close "<<socket<<std::endl;
        Multplex::disConnect(socket);
    }
public:
    NetUdp __server;
};

class My_tcp_mul : public Multplex{
public:
    My_tcp_mul(const int& count):Multplex(count){
        if(__server.bind(NetAddress(INADDR_ANY,8901),10)){
            std::cout<<"bind ok"<<std::endl;
            addSocket(__server.getSocket());
        }
    }

    void run_server(){
        while (server() != -1){

        }
    }

protected:
    bool read(int socket) override {
        if(socket == __server.getSocket()){
            NetTcp* client = __server.accept();
            if(client == nullptr){
                std::cout<<"new socket error"<<std::endl;
                return false;
            }else{
                std::cout<<"new socket"<<std::endl;
                addSocket(client->getSocket());
            }
        }else{
            NetTcp tcp(socket);
            int8_t buf[1024] = {};
            if(tcp.recv(buf,1023) <= 0)return false;
            std::cout<<"read "<<buf<<std::endl;
            int8_t sbuf[] = "my server";
            if(tcp.send(sbuf,sizeof(sbuf)) <= 0)return false;
        }
        return true;
    }
    void read(int socket,int8_t* data,const uint32_t& len) override {
        NetTcp tcp(socket);
        int8_t buf[1024] = {};
        memcpy((void*)buf,data, len);
        std::cout<<"socket "<<socket <<"  data: "<<buf<<" len "<<std::endl;
        int8_t sbuf[] = "my server";
        if(tcp.send(sbuf,sizeof(sbuf)) <= 0){
            std::cout<<"send error"<<std::endl;
        }
    }
    void disConnecct(int socket){
        std::cout<<"socket close "<<socket<<std::endl;
        Multplex::disConnect(socket);
    }

public:
    NetTcp __server;
};

TEST(NetBase_TEST,Tcp_Server){
    NetTcp tcp;
    NetAddress addr("127.0.0.1",8901);
    if(!tcp.bind(addr,3))std::cout<<"bind error"<<std::endl;
    char buf[100] = "";buf[99] = '\0';
    NetTcp* client = tcp.accept();
    if(tcp.recv((int8_t*)buf,sizeof(buf)-1) < 0)
        std::cout<<"recv error"<<std::endl;
    std::cout<<client->getAddr().getIp()<<"    "<<buf<<std::endl;
}

TEST(NetBase_TEST,Tcp_Base_Server){
//    sockaddr_in addr;
//    addr.sin_addr.S_un.S_addr = INADDR_ANY;
//    addr.sin_port = htons(9999);
//    addr.sin_family = AF_INET;
//
//    int r = NetBase::Base::net_bind(udp.getSocket(),(sockaddr*)&addr,sizeof(addr));
//    std::cout<<r<<std::endl;
//    char buf[100] = "";buf[99] = '\0';
//    NetAddress addru;
//    if(udp.recv(addru,buf,sizeof(buf)-1) < 0)
//        std::cout<<"recv error"<<std::endl;
//    std::cout<<addru.getIp()<<"    "<<buf<<std::endl;
}

TEST(Multplex_TEST,TCP_Server){
    My_tcp_mul mul(10);
    mul.run_server();
}

TEST(Multplex_TEST,UDP_Server){
    My_udp_mul mul(10);
    mul.run_server();
}

TEST(NetBase_TEST,UDP_Client){
    NetAddress server_addr("127.0.0.1",8811);
    NetBase::Test::netBase_Udp_Client(server_addr,"my 33 1 ",3);
}

TEST(NetBase_TEST,TCP_Client){
    NetAddress server_addr("127.0.0.1",8811);
    NetBase::Test::netBase_Tcp_Client(server_addr,"my 33 1 ",3);
}
